#ifndef PERCEPTRON_H_
#define PERCEPTRON_H_

#include "Neuron.h"
#include "DataSet.h"

/*
 * =====================================================================================
 *        Class:  Perceptron
 *  Description:  Classe que representa um perceptron
 * =====================================================================================
 */
class Perceptron
{

public:

    /*-----------------------------------------------------------------------------
     *  Constrói um perceptron passando o nº de variávies de entrada e de saída, a
     *  função de ativação e o aprendizado
     *-----------------------------------------------------------------------------*/
    Perceptron(uint nInVars, uint nOutVars, ActivationPtr activation,
            LearningPtr learning, CSVFilePtr csv = CSVFilePtr());

    /*-----------------------------------------------------------------------------
     *  Realiza o feedforward
     *-----------------------------------------------------------------------------*/
    vdoublePtr feedforward(vdoublePtr);

    /*-----------------------------------------------------------------------------
     *  Realiza o feedbackward na camada de saída
     *-----------------------------------------------------------------------------*/
    vdoublePtr feedbackward(vdoublePtr expected);

    /*-----------------------------------------------------------------------------
     *  Realiza o feedbackward na camada escondida
     *-----------------------------------------------------------------------------*/
    vdoublePtr feedbackward(vdoublePtr errors, vector<NeuronPtr>& nextNeurons);

    /*-----------------------------------------------------------------------------
     *  Atualiza o peso dos neurônios
     *-----------------------------------------------------------------------------*/
    void updateNeurons();

    /*-----------------------------------------------------------------------------
     *  Retorna o tamanho do vetor de neuronios
     *-----------------------------------------------------------------------------*/
    uint getNeuronSize() { return neurons.size(); }

    /*-----------------------------------------------------------------------------
     *  Retorna o neurônio de indice i
     *-----------------------------------------------------------------------------*/
    NeuronPtr getNeuron(uint i) { return neurons[i]; }

    /*-----------------------------------------------------------------------------
     *  Retorna os neurônios
     *-----------------------------------------------------------------------------*/
    vector<NeuronPtr>& getNeurons() { return neurons; }

    /*-----------------------------------------------------------------------------
     *  Imprime o perceptron
     *-----------------------------------------------------------------------------*/
    void print();

private:

    /*-----------------------------------------------------------------------------
     *  Número de variáveis de entrada
     *-----------------------------------------------------------------------------*/
    uint nInVars;

    /*-----------------------------------------------------------------------------
     *  Número de variáveis de saída
     *-----------------------------------------------------------------------------*/
    uint nOutVars;

    /*-----------------------------------------------------------------------------
     *  Neurônios
     *-----------------------------------------------------------------------------*/
    vector<NeuronPtr> neurons;

    /*-----------------------------------------------------------------------------
     *  Input recebido da camada anterior
     *-----------------------------------------------------------------------------*/
    vdoublePtr input; 

};

/*-----------------------------------------------------------------------------
 *  Ponteiro
 *-----------------------------------------------------------------------------*/
typedef boost::shared_ptr<Perceptron> PerceptronPtr;

#endif /* PERCEPTRON_H_ */
